package com.demo.main.dao.impl;

import com.demo.main.dao.BaseDao;
import com.demo.main.utils.JDBCUtil;
import com.demo.main.utils.PaginationUtil;
import com.demo.main.utils.ResultSetUtil;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.Map;

// 定义一个抽象类BaseDaoImpl，实现BaseDao接口，泛型T代表实体类类型，E代表主键类型
public abstract class BaseDaoImpl<T, E> implements BaseDao<T, E> {
    // 私有成员变量，用于操作数据库的JDBCUtil实例
    private final JDBCUtil jdbcUtil;
    // 私有成员变量，保存实体类的Class对象，用于反射操作
    private final Class<T> tClass;
    // 私有成员变量，保存主键列的名称
    private final String primaryKeyColumn;

    // 构造方法，初始化jdbcUtil、tClass和primaryKeyColumn
    public BaseDaoImpl(String tableName, String primaryKeyColumn, Class<T> tClass) {
        jdbcUtil = new JDBCUtil("`" + tableName + "`", "`" + primaryKeyColumn + "`");
        this.tClass = tClass;
        this.primaryKeyColumn = primaryKeyColumn;
    }

    // 构造方法重载，默认主键列为"id"
    public BaseDaoImpl(String tableName, Class<T> tClass) {
        this(tableName, "id", tClass);
    }

    // 实现接口方法，查询所有记录
    @Override
    public List<T> selectAll() {
        return ResultSetUtil.mapToList(jdbcUtil.selectAll(), tClass);
    }

    // 实现接口方法，按主键降序查询所有记录
    @Override
    public List<T> selectAllByDesc() {
        return ResultSetUtil.mapToList(jdbcUtil.selectDescById(), tClass);
    }

    // 实现接口方法，根据条件查询记录
    @Override
    public List<T> selectByCondition(T entity) {
        return ResultSetUtil.mapToList(jdbcUtil.selectSelective(entity), tClass);
    }

    // 实现接口方法，根据条件按主键降序查询记录
    @Override
    public List<T> selectByConditionDesc(T entity) {
        return ResultSetUtil.mapToList(jdbcUtil.selectSelectiveDescById(entity), tClass);
    }

    // 实现接口方法，根据条件查询单条记录
    @Override
    public T selectOneByCondition(T entity) {
        return ResultSetUtil.mapToSingle(jdbcUtil.selectSelective(entity), tClass);
    }

    // 实现接口方法，插入单条记录
    @Override
    public void insertOne(T entity) {
        jdbcUtil.insertSelective(entity);
    }

    // 实现接口方法，根据主键删除记录
    @Override
    public void deleteById(E id) {
        jdbcUtil.deleteById(id);
    }

    // 实现接口方法，批量删除记录
    @Override
    public void batchDeleteByIds(List<?> ids) {
        jdbcUtil.deleteByIds(ids);
    }

    // 实现接口方法，根据主键更新记录
    @Override
    public void updateById(T entity) {
        jdbcUtil.updateSelective(entity);
    }

    // 实现接口方法，根据主键查询单条记录
    @Override
    public T selectOneById(E id) {
        return ResultSetUtil.mapToSingle(jdbcUtil.selectById(id), tClass);
    }

    // 实现接口方法，根据主键查询记录（方法名与selectOneById冲突，可能是为了重载不同返回类型）
    @Override
    public List<T> selectById(E id) {
        return ResultSetUtil.mapToList(jdbcUtil.selectById(id), tClass);
    }

    // 实现接口方法，根据列名和值查询记录
    @Override
    public List<T> selectByColumn(String column, Object value) {
        return ResultSetUtil.mapToList(jdbcUtil.selectByColumn(column, value), tClass);
    }

    // 实现接口方法，根据列名和值按主键降序查询记录
    @Override
    public List<T> selectByColumnDesc(String column, Object value) {
        return ResultSetUtil.mapToList(jdbcUtil.selectByColumnDescById(column, value), tClass);
    }

    // 实现接口方法，根据列名和值查询单条记录
    @Override
    public T selectOneByColumn(String column, Object value) {
        return ResultSetUtil.mapToSingle(jdbcUtil.selectByColumn(column, value), tClass);
    }

    // 实现接口方法，查询记录总数
    @Override
    public Integer selectCount() {
        return Math.toIntExact(jdbcUtil.selectCount());
    }

    // 实现接口方法，根据条件查询记录总数
    @Override
    public Integer selectCountByCondition(T entity) {
        return Math.toIntExact(jdbcUtil.selectCountByCondition(entity));
    }

    // 实现接口方法，分页查询记录（按降序）
    @Override
    public List<T> selectPagination(Integer pageNum) {
        return ResultSetUtil.mapToList(jdbcUtil.selectPaginationDesc(pageNum), tClass);
    }

    // 实现接口方法，根据条件分页查询记录（按主键降序）
    @Override
    public List<T> selectSelectivePagination(int pageNum, T entity) {
        return ResultSetUtil.mapToList(jdbcUtil.selectSelectivePaginationDescById(entity, pageNum), tClass);
    }

    // 自定义方法，带详情的分页查询（降序）
    public <D> List<D> selectAllWithDetailsDesc(String sql, Class<D> dtoClass, int pageNum) {
        return ResultSetUtil.mapToList(JDBCUtil.executeConditionalQueryWithOrderAndPagination(sql, null, Collections.singletonMap(primaryKeyColumn, false), pageNum, PaginationUtil.DEFAULT_PAGE_SIZE), dtoClass);
    }

    // 自定义方法，根据条件带详情的分页查询（降序）
    public <D> List<D> selectByConditionWithDetailsDesc(String sql, Map<String, Object> conditions, Class<D> dtoClass, int pageNum) {
        return ResultSetUtil.mapToList(JDBCUtil.executeConditionalQueryWithOrderAndPagination(sql, conditions, Collections.singletonMap(primaryKeyColumn, false), pageNum, PaginationUtil.DEFAULT_PAGE_SIZE), dtoClass);
    }

    // 自定义方法重载，允许指定主键列进行带详情的分页查询（降序）
    public <D> List<D> selectAllWithDetailsDesc(String sql, String primaryKey, Class<D> dtoClass, int pageNum) {
        return ResultSetUtil.mapToList(JDBCUtil.executeConditionalQueryWithOrderAndPagination(sql, null, Collections.singletonMap(primaryKey, false), pageNum, PaginationUtil.DEFAULT_PAGE_SIZE), dtoClass);
    }

    // 自定义方法，带详情的查询总数
    public int selectAllCountWithDetails(String sql) {
        return JDBCUtil.selectConditionalQueryCount(sql, null);
    }

    // 自定义方法，根据条件带详情的查询总数
    public int selectCountByConditionWithDetails(String sql, Map<String, Object> conditions) {
        return JDBCUtil.selectConditionalQueryCount(sql, conditions);
    }

    // 自定义方法，调用存储过程
    public JDBCUtil.StoredProcedureResult callStoredProcedure(String procedureName, Object... params) throws SQLException {
        return JDBCUtil.callStoredProcedure(procedureName, params);
    }
}